/*
 * PhotonRTOS础光实时操作系统 -- os_application
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <autosar/internal.h>
#include <photon/timex.h>

VAR(OsOsAppType, AUTOMATIC) autosar_os_app[AUTOSAR_NR_APPLICATION];
VAR(OsTrustedFuncType, AUTOMATIC) autosar_trusted_func[MAX_TRUSTED_FUNC_NUM];
VAR(bool, AUTOMATIC) time_protect_table[MAX_CPUS];

#if (defined(AUTOSAR_OS_APPLICATION) || defined(AUTOSAR_MULTICORE))
FUNC(ApplicationType, OS_CODE) GetApplicationID(void)
{
	VAR(ApplicationType, AUTOMATIC) app_id;

#if defined(EXTENDED_STATUS)
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc;
#endif

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK \
	| ENV_PRETASK_HOOK | ENV_STARTUP_HOOK | ENV_POSTTASK_HOOK\
	| ENV_SHUTDOWN_HOOK | ENV_PROTECTION_HOOK)

#if defined(EXTENDED_STATUS)
	pro_desc = current_proc_info();
	/**
	 * [SWS_Os_00262] [如果当前没有app在运行，就返回INVALID_OSAPPLICATION.]
	*/
	if (pro_desc == NULL || pro_desc->object.app_id >= INVALID_OSAPPLICATION) {
		app_id = INVALID_OSAPPLICATION;
		goto out;
	}
#endif

	app_id = autosar_get_application_id();
out:
	return app_id;
}
#endif /* (defined(AUTOSAR_OS_APPLICATION) || defined(AUTOSAR_MULTICORE)) */

#if defined(AUTOSAR_OS_APPLICATION)
FUNC(StatusType, OS_CODE) GetApplicationState(
	VAR(ApplicationType, AUTOMATIC) Application,
	VAR(ApplicationStateRefType, AUTOMATIC) Value)
{
	VAR(StatusType, AUTOMATIC) status;

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK \
		| ENV_PRETASK_HOOK | ENV_STARTUP_HOOK | ENV_POSTTASK_HOOK \
		| ENV_SHUTDOWN_HOOK | ENV_PROTECTION_HOOK)

#if defined(EXTENDED_STATUS)
	if (Application >= AUTOSAR_NR_APPLICATION) {
		status = E_OS_ID;
		goto out;
	}
#endif

	status = autosar_get_application_state(Application, Value);
out:
	return status;
}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(AUTOSAR_OS_APPLICATION)
/**
 * 注意：如果此函数不是通过CallTrustedFunction()调用的，那么其结果总是和GetApplicationID()相同
*/
FUNC(ApplicationType, OS_CODE) GetCurrentApplicationID(void)
{
	VAR(ApplicationType, AUTOMATIC) app_id;

#if defined(EXTENDED_STATUS)
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
#endif

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK \
		| ENV_PRETASK_HOOK | ENV_STARTUP_HOOK | ENV_POSTTASK_HOOK \
		| ENV_SHUTDOWN_HOOK | ENV_PROTECTION_HOOK)

#if defined(EXTENDED_STATUS)
	/**
	 * [SWS_Os_00262] [如果当前没有app在运行，就返回INVALID_OSAPPLICATION.]
	*/
	if (pro_desc == NULL || pro_desc->object.app_id == -1 ||
		pro_desc->object.app_id >= AUTOSAR_NR_APPLICATION) {
		app_id = INVALID_OSAPPLICATION;
		goto out;
	}
#endif

	app_id = autosar_get_current_application_id();
out:
	return app_id;
}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(AUTOSAR_OS_APPLICATION)
FUNC(StatusType, OS_CODE) TerminateApplication(
	VAR(ApplicationType, AUTOMATIC) Application,
	VAR(RestartType, AUTOMATIC) RestartOption)
{
	StatusType ret;
	ApplicationType caller_app_id = current_proc_info()->object.app_id;

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK)

#if defined(EXTENDED_STATUS)
	/**
	 * [SWS_Os_00493] ⌈如果TerminateApplication ()调用中的输入参数 <Application>无效，则TerminateApplication () 应返回E_OS_ID。 ⌋ ( )
	 */
	if (Application >= AUTOSAR_NR_APPLICATION) {
		ret = E_OS_ID;
		goto out;
	}
	/**
	 * [SWS_Os_00459] ⌈如果TerminateApplication ()调用中的 <RestartOption>无效，则TerminateApplication () 应返回E_OS_VALUE。 ⌋ ( )
	 */
	if (RestartOption != RESTART && RestartOption != NO_RESTART) {
		ret = E_OS_VALUE;
		goto out;
	}

	/**
	 * [SWS_Os_00494] ⌈如果	TerminateApplication ()调用中的输入参数 <Application>有效且调用者属于不可信的 OSApplication 并且调用者不属于 <Application> TerminateApplication () 应返回E_OS_ACCESS。 ⌋ ( )
	 */
	if (autosar_os_app[caller_app_id].if_trusted == 0 && caller_app_id != Application) {
		ret = E_OS_ACCESS;
		goto out;
	}

	/**
	 * [SWS_Os_00507] ⌈如果	TerminateApplication ()	调用中<Application>的状态为APPLICATION_TERMINATED TerminateApplication () 应返回E_OS_STATE。 ⌋ ( )
	 */
	if (autosar_os_app[Application].state == APPLICATION_TERMINATED) {
		ret = E_OS_STATE;
		goto out;
	}

	/**
	 * [SWS_Os_00508] ⌈如果在TerminateApplication () 调用中 <Application> 的状态是APPLICATION_RESTARTING并且调用者不属于 <Application> 则TerminateApplication () 应返回E_OS_STATE。 ⌋ ( )
	 */
	if (autosar_os_app[Application].state == APPLICATION_RESTARTING &&
		caller_app_id != Application) {
		ret = E_OS_STATE;
		goto out;
	}

	/**
	 * [SWS_Os_00548] ⌈如果在TerminateApplication () 的调用中 <Application> 的状态是APPLICATION_RESTARTING并且调用者确实属于 <Application> 并且 <RestartOption> 等于RESTART那么TerminateApplication () 将返回E_OS_STATE 。 ⌋ ( )
	 */
	if (autosar_os_app[Application].state == APPLICATION_RESTARTING &&
		caller_app_id == Application && RestartOption == RESTART) {
		ret = E_OS_STATE;
		goto out;
	}
#endif
	SuspendAllInterrupts();
	ret = autosar_terminate_application(Application, RestartOption);
	ResumeAllInterrupts();

out:
	/**
	 * 如果出现错误，就调用错误钩子
	 * 如果没有配置错误钩子宏，
	 * 编译器会做优化，不用担心。
	 */
	if (ret != E_OK) {
		osek_call_hook_0(TerminateApplication, ret);
	}
	return ret;
}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(AUTOSAR_OS_APPLICATION)
FUNC(void, OS_CODE) application_init(void)
{
	VAR(int32_t, AUTOMATIC) i, j;

	/**
	 * [SWS_Os_00500] 操作系统模块应在调用StartOS()之后和在任何 StartupHook 被调用之前设置所有
	 * OS-Applications 的状态为 APPLICATION_ACCESSIBLE 。
	 */
	for (i = 0; i < AUTOSAR_NR_APPLICATION; i++) {
		autosar_os_app[i].state = APPLICATION_ACCESSIBLE;
		autosar_os_app[i].core_id = i;
		autosar_os_app[i].if_trusted = 1;
		autosar_os_app[i].startup_hook = autosar_os_app_attr[i].startup_hook;
		autosar_os_app[i].shutdown_hook = autosar_os_app_attr[i].shutdown_hook;
		autosar_os_app[i].error_hook = autosar_os_app_attr[i].error_hook;
	}

	for (i = 0; i < AUTOSAR_NR_SCHEDULE_TABLE; i++) {
		for (j = 0; j < AUTOSAR_NR_APPLICATION; j++)
			autosar_schedule_tables[i].object.accessable_application_id[j] = 1;
		if (i <= AUTOSAR_NR_SCHEDULE_TABLE / 2) {
			autosar_schedule_tables[i].object.app_id = 0;
		} else {
			autosar_schedule_tables[i].object.app_id = 1;
		}
		autosar_schedule_tables[i].object.object_type = TYPE_SCHEDULE_TABLE;
	}

	for (i = 0; i < AUTOSAR_NR_COUNTER; i++) {
		if (i <= AUTOSAR_NR_COUNTER / 2) {
			autosar_counters[i].object.app_id = 0;
		} else {
			autosar_counters[i].object.app_id = 1;
		}

		for (j = 0; j < AUTOSAR_NR_APPLICATION; j++)
			autosar_counters[i].object.accessable_application_id[j] = 1;
		autosar_counters[i].object.object_type = TYPE_COUNTER;
	}
}

FUNC(void, OS_CODE) TRUSTED_Test_Service0(
	VAR(TrustedFunctionIndexType,AUTOMATIC) func_index,
	VAR(TrustedFunctionParameterRefType, AUTOMATIC) param)
{
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
	pr_debug("%s, %d, app_id :%d\n", __func__, __LINE__, app_id);
}

FUNC(void, OS_CODE) TRUSTED_Test_Service1(
	VAR(TrustedFunctionIndexType, AUTOMATIC) func_index,
	VAR(TrustedFunctionParameterRefType, AUTOMATIC) param)
{
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
	pr_debug("%s, %d, app_id :%d\n", __func__, __LINE__, app_id);
}

FUNC(void, OS_CODE) trusted_func_init(void)
{
	VAR(int32_t, AUTOMATIC) i, j;

	for (i = 0; i < MAX_TRUSTED_FUNC_NUM; i++) {
		for (j = 0; j < AUTOSAR_NR_APPLICATION; j++)
			autosar_trusted_func[i].accessable_application_id[j] = 1;
	}

	autosar_trusted_func[0].app_id = 0;
	autosar_trusted_func[0].trusted_func = TRUSTED_Test_Service0;

	autosar_trusted_func[1].app_id = 1;
	autosar_trusted_func[1].trusted_func = TRUSTED_Test_Service1;
}

#endif /* defined(AUTOSAR_OS_APPLICATION) */

/**
 * [SWS_Os_00608] 如果多个核心调用StartOS的 AppMode 不是“ DONOTCARE ”，则 AppModes 应相同。
 * StartOS将在第一个同步点检查这一点。如果违反， StartOS不会启动调度，
 * 不会调用任何StartupHooks ，并且会在每个核心上进入无限循环。
 */
FUNC(void, OS_CODE) check_app_mode(void)
{
	VAR(int32_t, AUTOMATIC) i;
	VAR(AppModeType, AUTOMATIC) tmpMode, finalMode;

	finalMode = DONOTCARE;

	for (i = 0; i < MAX_CPUS; i++) {
		tmpMode = autosar_get_app_mode(i);
		if (tmpMode != DONOTCARE) {
			finalMode = tmpMode;
		}
	}

	if (finalMode == DONOTCARE) { /* all DONOTCARE mode! */
		pr_err("app mode all DONOTCARE!!!\n");
		for (;;)
			;
	}

	finalMode = DONOTCARE;
	for (i = 0; i < MAX_CPUS; i++) {
		tmpMode = autosar_get_app_mode(i);
		if (tmpMode != DONOTCARE) {
			if (finalMode == DONOTCARE) {
				finalMode = tmpMode;
			} else {

				if (finalMode != tmpMode) {
					pr_err("app mode must be one!!!\n");
					for (;;)
						;
				}
			}
		}
	}

	ASSERT(finalMode != DONOTCARE);

	/**
	 * [SWS_Os_00609] ⌈如果使用AppMode “ DONOTCARE ”调用 StartOS，
	 * 则应使用其他核心的应用模式（不同于“ DONOTCARE ”）。
	 */
	for (i = 0; i < MAX_CPUS; i++) {
		tmpMode = autosar_get_app_mode(i);
		if (tmpMode == DONOTCARE) {
			autosar_set_app_mode(i, finalMode);
		}
	}
}


FUNC(ApplicationType, OS_CODE) autosar_get_application_id(void)
{
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	/**
	 * [SWS_Os_00261] [返回所属的app_id.]
	*/
	return pro_desc->object.app_id;
}

#if defined(AUTOSAR_OS_APPLICATION)
FUNC(ApplicationType, OS_CODE) autosar_get_current_application_id(void)
{
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	/**
	 * [SWS_Os_00262] [如果当前没有app在运行，就返回INVALID_OSAPPLICATION.]
	*/
	if (pro_desc == NULL) {
		return INVALID_OSAPPLICATION;
	}
	/**
	 * [SWS_Os_00261] [返回所属的app_id.]
	*/
	return pro_desc->object.app_id;
}

FUNC(ObjectAccessType, OS_CODE) autosar_check_object_access(
	VAR(ApplicationType, AUTOMATIC) ApplID,
	VAR(ObjectTypeType, AUTOMATIC) ObjectType,
	P2VAR(void, AUTOMATIC, OS_APPL_DATA) object)
{
	VAR(OsObjectRefType, AUTOMATIC) obj = (OsObjectRefType) object;

	if (obj->accessable_application_id[ApplID] == 1 &&
		autosar_os_app[obj->app_id].state == APPLICATION_ACCESSIBLE) {
		/**
		 * [SWS_Os_00271] 如果有权限访问object，则返回ACCESS。
		*/
		return ACCESS;

	} else {
		/**
		 * [SWS_Os_00272] 如果ApplID值定的os-app没有权限访问object，则返回NO_ACCESS;s
		*/
		return NO_ACCESS;
	}
}

FUNC(ApplicationType, OS_CODE) autosar_check_object_ownership(
	VAR(ObjectTypeType, AUTOMATIC) ObjectType,
	P2VAR(void, AUTOMATIC, OS_APPL_DATA) object)
{
	VAR(OsObjectRefType, AUTOMATIC) obj = (OsObjectRefType) object;

	/**
	 * [SWS_Os_00273] 返回app_id
	*/
	return obj->app_id;
}

FUNC(StatusType, OS_CODE) autosar_allow_access(void)
{
	VAR(ApplicationType, AUTOMATIC) caller_app_id = current_proc_info()->object.app_id;

	autosar_os_app[caller_app_id].state = APPLICATION_RESTARTING;
	return E_OK;
}

/**
 * [SWS_Os_00536] ⌈ TerminateApplication ()的可用性：在可扩展性等级 3 和 4 中可用。⌋ ( )
 * []注意：虽然受信任的操作系统应用程序可以被其他受信任的操作系统应
 * 用程序的任务/中断强行终止，但不建议这样做。这可能会产生进一步的影
 * 响，例如对当前通过CallTrustedFunction()调用属于此类 OS 应用程序的用户的影
 * 响。
 */
FUNC(StatusType, OS_CODE) autosar_terminate_application(
	VAR(ApplicationType, AUTOMATIC) Application,
	VAR(RestartType, AUTOMATIC) RestartOption)
{
	int32_t i;

	/**
	 * [SWS_Os_00287] ⌈如果TerminateApplication ()调用中的参数有效且满足上述条件，则TerminateApplication () 将终止 <Application>（即终止所有任务，禁用那些属于 OS 的 ISR 的中断源-应用程序并释放与应用程序相关的所有其他操作系统资源）并且如果 <RestartOption> 等于RESTART则应激活 <Application> 的配置OsRestartTask 。如果没有配置OsRestartTask ，则不会发生重启。如果 <Application> 重新启动，则其状态设置为APPLICATION_RESTARTING否则设置为APPLICATION_TERMINATED 。如果调用者属于 <Application> TerminateApplication () 则不应返回，否则应返回E_OK 。 ⌋ ( )
	 */
	/**
	 * (1)Release Lock
	 */
	for (i = 0; i < AUTOSAR_NR_SPIN_LOCK; i++) {
		if (smp_lock_is_locked(&autosar_spin_locks[i].smp_lock) &&
			autosar_spin_locks[i].owner_app_id == Application) {
			if (autosar_spin_locks[i].owner_core_id == GetCoreID()) {
				/**
				 * 如果在调用terminate_app()之前，当前core已经持有了terminate_app()要释放的自旋锁，说明代码逻辑出问题了。
				 */
				BUG();
			}
		}
	}

	/**
	 * (2)Release Resource
	 * (3)Terminate Task
	 */
	for (i = 0; i <OS_NR_TASK; i++) {
		if (osek_tasks[i].app_id == Application) {
			osek_tasks[i].resource_mask = 0;
			osek_tasks[i].sched_prio = osek_tasks[i].prio;

			osek_tasks[i].state = SUSPENDED;
			del_from_runqueue(&osek_tasks[i]);
			if (current->osek_id == osek_tasks[i].osek_id) {
				set_task_need_resched(current);
			}
		}
	}
	/**
	 * (4)stop schedule_table
	 */
	for (i = 0; i < AUTOSAR_NR_SCHEDULE_TABLE; i++) {
		if (autosar_schedule_tables[i].object.app_id == Application) {
			StopScheduleTable(i);
		}
	}

	/**
	 * [SWS_Os_00287] 如果 RestartOption == RESTART，os-app状态设置为APPLICATION_RESTARTING，否则设置为APPLICATION_TERMINATED
	 */
	if (RestartOption == RESTART) {
		autosar_os_app[Application].state = APPLICATION_RESTARTING;
	} else {
		autosar_os_app[Application].state = APPLICATION_TERMINATED;
	}

	return 0;
}

FUNC(StatusType, OS_CODE) autosar_get_application_state(
	VAR(ApplicationType, AUTOMATIC) Application,
	VAR(ApplicationStateRefType, AUTOMATIC) Value)
{
	*Value = autosar_os_app[Application].state;

	return E_OK;
}

FUNC(StatusType, OS_CODE) autosar_activate_task_async(TaskType TaskID, ApplicationType CallerAppId)
{
#ifdef AUTOSAR_TIMING_PROTECTION
	uint64_t activate_time;
#endif
	VAR(StatusType, AUTOMATIC) ret = E_OK;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) target_pro_desc
		= osek_tasks[TaskID].stack;

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 */
	if (target_pro_desc == NULL || TaskID >=OS_NR_TASK) {
		/**
		 * 根据OSEK规范，当ID过大时，返回E_OS_ID
		 * 注意这里TaskType为无符号数
		 */
		ret = E_OS_ID;
		goto out;
	}
	/**
	 * 在扩展模式下，检查是否有权访问app_id。
	 */
#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(CallerAppId, TYPE_TASK, &target_pro_desc->object) != ACCESS) {
		ret = E_OS_ID;
		goto out;
	}
#endif
#endif
#ifdef AUTOSAR_TIMING_PROTECTION
	activate_time = percpu_last_task_activate_time;
	/**
	 * [SWS_Os_00465] [OS Module应该保证两次任务激活的间隔时间在OsTaskTimeFrame以上]
	 * (1)percpu_last_task_activate_time == 0 表示第一次被激活。
	 * (2)两次激活时间超过了autosar_time_frame的规定值.(微秒为单位)
	 * 以上两种情况可以正常激活，否则就触发 时间保护钩子
	*/
	if (time_protect_disable == 0 && activate_time != 0 &&
		osek_tasks[TaskID].cp_attr.cp_task_time_frame + activate_time >
		(cycles_to_usecs(get_cycles()))) {
		pr_err("ProtectionHook E_OS_PROTECTION_ARRIVAL\n");
		autosar_protect_hook(E_OS_PROTECTION_ARRIVAL);
	}
	/**
	 * [SWS_Os_00469] [当任务被激活时OsTaskTimeFrame应该开始计数]
	*/
	percpu_last_task_activate_time = cycles_to_usecs(get_cycles());
#endif
	SuspendAllInterrupts();

	ret = __osek_activate_task(TaskID);
	/**
	 * 注意，这里可能有重调度
	 */
	ResumeAllInterrupts();

out:
	return ret;
}


FUNC(StatusType, OS_CODE) autosar_set_event_async(TaskType TaskID, EventMaskType Mask,
	ApplicationType caller_app_id)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) target_pro_desc
		= osek_tasks[TaskID].stack;

#if defined(EXTENDED_STATUS)
	if (TaskID >=OS_NR_TASK) {
		/**
		 * 根据OSEK规范，当ID过大时，返回E_OS_ID
		 * 注意这里TaskType为无符号数
		 */
		ret = E_OS_ID;
		goto out;
	}

	/**
	 * 在扩展模式下，检查是否有权访问app_id。
	 */
#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(caller_app_id, TYPE_TASK, &target_pro_desc->object) != ACCESS) {
		ret = E_OS_ID;
		goto out;
	}
#endif
	/**
	 * 在扩展模式下，检查当前任务是否为扩展任务
	 * 非扩展任务（基本任务）不支持事件，
	 * 也就不能调用本函数
	 */
	if ((osek_tasks[TaskID].flags & TF_EXTENDED) != TF_EXTENDED) {
		ret = E_OS_ACCESS;
		goto out;
	}

	/**
	 * 如果目标任务处于挂起状态，就不能设置其事件状态
	 */
	if (osek_tasks[TaskID].state == SUSPENDED) {
		ret = E_OS_STATE;
		goto out;
	}
#endif

	SuspendAllInterrupts();

	__osek_set_event(TaskID, Mask);

	/**
	 * 注意，这里可能有重调度
	 */
	ResumeAllInterrupts();

out:

	return ret;
}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(CONFIG_AUTOSAR_APPLICATION_HOOK_STARTUP)
FUNC(void, OS_CODE) os_app_startup_hooks(void)
{
	VAR(int32_t, AUTOMATIC) i;
	VAR(CoreIdType, AUTOMATIC) core_id = GetCoreID();
	VAR(OsApplicationHook, AUTOMATIC) hook;

	for (i = 0; i < AUTOSAR_NR_APPLICATION; i++) {
		hook = autosar_os_app[i].startup_hook;
		if (hook != NULL && core_id == autosar_os_app[i].core_id) {
			hook();
		}
	}
}
#endif

#if defined(CONFIG_AUTOSAR_APPLICATION_HOOK_SHUTDOWN)
FUNC(void, OS_CODE) os_app_shutdown_hooks(void)
{
	VAR(int32_t, AUTOMATIC) i;
	VAR(CoreIdType, AUTOMATIC) core_id = GetCoreID();
	VAR(OsApplicationHook, AUTOMATIC) hook;

	for (i = 0; i < AUTOSAR_NR_APPLICATION; i++) {
		hook = autosar_os_app[i].shutdown_hook;
		if (hook != NULL && core_id == autosar_os_app[i].core_id) {
			hook();
		}
	}
}
#endif

FUNC(void, OS_CODE) autosar_call_trusted_function(
	VAR(TrustedFunctionIndexType, AUTOMATIC) FunctionIndex,
	VAR(TrustedFunctionParameterRefType, AUTOMATIC) FunctionParams)
{
	OsTrustedFuncRefType trusted_func = autosar_trusted_func[FunctionIndex].trusted_func;

	trusted_func(FunctionIndex, FunctionParams);
}
